#include <sys/types.h>
#include <fcntl.h>
#include <sys/select.h>
+#include <sys/mman.h>
#include <sys/wait.h>
#include <signal.h>
#include <unistd.h> /* for write, unlink and close */
vments[i++] = "image/ostype";
vments[i++] = "linux";
vments[i++] = "image/kernel";
- vments[i++] = (char*) info->kernel;
+ vments[i++] = (char*) info->kernel.path;
vments[i++] = "start_time";
vments[i++] = libxl_sprintf(ctx, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000);
- if (info->u.pv.ramdisk) {
+ if (info->u.pv.ramdisk.path) {
vments[i++] = "image/ramdisk";
- vments[i++] = (char*) info->u.pv.ramdisk;
+ vments[i++] = (char*) info->u.pv.ramdisk.path;
}
if (info->u.pv.cmdline) {
vments[i++] = "image/cmdline";
}
ret = build_post(ctx, domid, info, state, vments, localents);
out:
+ libxl_file_reference_unmap(ctx, &info->kernel);
+ if (!info->hvm)
+ libxl_file_reference_unmap(ctx, &info->u.pv.ramdisk);
+
return ret;
}
vments[i++] = "image/ostype";
vments[i++] = "linux";
vments[i++] = "image/kernel";
- vments[i++] = (char*) info->kernel;
+ vments[i++] = (char*) info->kernel.path;
vments[i++] = "start_time";
vments[i++] = libxl_sprintf(ctx, "%lu.%02d", start_time.tv_sec,(int)start_time.tv_usec/10000);
- if (info->u.pv.ramdisk) {
+ if (info->u.pv.ramdisk.path) {
vments[i++] = "image/ramdisk";
- vments[i++] = (char*) info->u.pv.ramdisk;
+ vments[i++] = (char*) info->u.pv.ramdisk.path;
}
if (info->u.pv.cmdline) {
vments[i++] = "image/cmdline";
}
out:
+ libxl_file_reference_unmap(ctx, &info->kernel);
+ if (!info->hvm)
+ libxl_file_reference_unmap(ctx, &info->u.pv.ramdisk);
+
esave = errno;
flags = fcntl(fd, F_GETFL);
b_info.max_vcpus = 1;
b_info.max_memkb = 32 * 1024;
b_info.target_memkb = b_info.max_memkb;
- b_info.kernel = libxl_abs_path(ctx, "ioemu-stubdom.gz", libxl_xenfirmwaredir_path());
+ b_info.kernel.path = libxl_abs_path(ctx, "ioemu-stubdom.gz", libxl_xenfirmwaredir_path());
b_info.u.pv.cmdline = libxl_sprintf(ctx, " -d %d", info->domid);
- b_info.u.pv.ramdisk = "";
+ b_info.u.pv.ramdisk.path = "";
b_info.u.pv.features = "";
b_info.hvm = 0;
return rc;
}
+int libxl_file_reference_map(struct libxl_ctx *ctx, libxl_file_reference *f)
+{
+ struct stat st_buf;
+ int ret, fd;
+ void *data;
+
+ if (f->mapped)
+ return 0;
+
+ fd = open(f->path, O_RDONLY);
+ if (f < 0)
+ return ERROR_FAIL;
+
+ ret = fstat(fd, &st_buf);
+ if (ret < 0)
+ goto out;
+
+ ret = -1;
+ data = mmap(NULL, st_buf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (data == NULL)
+ goto out;
+
+ f->mapped = 1;
+ f->data = data;
+ f->size = st_buf.st_size;
+
+ ret = 0;
+out:
+ close(fd);
+
+ return ret == 0 ? 0 : ERROR_FAIL;
+}
+
+int libxl_file_reference_unmap(struct libxl_ctx *ctx, libxl_file_reference *f)
+{
+ int ret;
+
+ if (!f->mapped)
+ return 0;
+
+ ret = munmap(f->data, f->size);
+
+ return ret == 0 ? 0 : ERROR_FAIL;
+}
char *poolname;
} libxl_domain_create_info;
+typedef struct {
+ /*
+ * Path is always set if the file refernece is valid. However if
+ * mapped is true then the actual file may already be unlinked.
+ */
+ char *path;
+ int mapped;
+ void *data;
+ size_t size;
+} libxl_file_reference;
+
+/*
+ * Instances of libxl_file_reference contained in this struct which
+ * have been mapped (with libxl_file_reference_map) will be unmapped
+ * by libxl_domain_build/restore. If either of these are never called
+ * then the user is responsible for calling
+ * libxl_file_reference_unmap.
+ */
typedef struct {
int max_vcpus;
int cur_vcpus;
uint32_t video_memkb;
uint32_t shadow_memkb;
bool disable_migrate;
- const char *kernel;
+ libxl_file_reference kernel;
int hvm;
union {
struct {
struct {
uint32_t slack_memkb;
const char *cmdline;
- const char *ramdisk;
+ libxl_file_reference ramdisk;
const char *features;
} pv;
} u;
int libxl_domain_shutdown(struct libxl_ctx *ctx, uint32_t domid, int req);
int libxl_domain_destroy(struct libxl_ctx *ctx, uint32_t domid, int force);
+int libxl_file_reference_map(struct libxl_ctx *ctx, libxl_file_reference *f);
+int libxl_file_reference_unmap(struct libxl_ctx *ctx, libxl_file_reference *f);
+
char *libxl_uuid2string(struct libxl_ctx *ctx, uint8_t uuid[16]);
/* 0 means ERROR_ENOMEM, which we have logged */
int ret;
int flags = 0;
+ xc_dom_loginit(ctx->xch);
+
dom = xc_dom_allocate(ctx->xch, info->u.pv.cmdline, info->u.pv.features);
if (!dom) {
XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xc_dom_allocate failed");
- return -1;
+ return ERROR_FAIL;
+ }
+
+ if (info->kernel.mapped) {
+ if ( (ret = xc_dom_kernel_mem(dom, info->kernel.data, info->kernel.size)) != 0) {
+ XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xc_dom_kernel_mem failed");
+ goto out;
+ }
+ } else {
+ if ( (ret = xc_dom_kernel_file(dom, info->kernel.path)) != 0) {
+ XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xc_dom_kernel_file failed");
+ goto out;
+ }
}
- ret = xc_dom_linux_build(ctx->xch, dom, domid, info->target_memkb / 1024,
- info->kernel, info->u.pv.ramdisk, flags,
- state->store_port, &state->store_mfn,
- state->console_port, &state->console_mfn);
- if (ret != 0) {
- xc_dom_release(dom);
- XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, ret, "xc_dom_linux_build failed");
- return -2;
+
+ if ( info->u.pv.ramdisk.path && strlen(info->u.pv.ramdisk.path) ) {
+ if (info->u.pv.ramdisk.mapped) {
+ if ( (ret = xc_dom_ramdisk_mem(dom, info->u.pv.ramdisk.data, info->u.pv.ramdisk.size)) != 0 ) {
+ XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xc_dom_ramdisk_mem failed");
+ goto out;
+ }
+ } else {
+ if ( (ret = xc_dom_ramdisk_file(dom, info->u.pv.ramdisk.path)) != 0 ) {
+ XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xc_dom_ramdisk_file failed");
+ goto out;
+ }
+ }
}
+
+ dom->flags = flags;
+ dom->console_evtchn = state->console_port;
+ dom->xenstore_evtchn = state->store_port;
+
+ if ( (ret = xc_dom_boot_xen_init(dom, ctx->xch, domid)) != 0 ) {
+ XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xc_dom_boot_xen_init failed");
+ goto out;
+ }
+ if ( (ret = xc_dom_parse_image(dom)) != 0 ) {
+ XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xc_dom_parse_image failed");
+ goto out;
+ }
+ if ( (ret = xc_dom_mem_init(dom, info->target_memkb / 1024)) != 0 ) {
+ XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xc_dom_mem_init failed");
+ goto out;
+ }
+ if ( (ret = xc_dom_boot_mem_init(dom)) != 0 ) {
+ XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xc_dom_boot_mem_init failed");
+ goto out;
+ }
+ if ( (ret = xc_dom_build_image(dom)) != 0 ) {
+ XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xc_dom_build_image failed");
+ goto out;
+ }
+ if ( (ret = xc_dom_boot_image(dom)) != 0 ) {
+ XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "xc_dom_boot_image failed");
+ goto out;
+ }
+
+ state->console_mfn = xc_dom_p2m_host(dom, dom->console_pfn);
+ state->store_mfn = xc_dom_p2m_host(dom, dom->xenstore_pfn);
+
+ ret = 0;
+out:
xc_dom_release(dom);
- return 0;
+ return ret == 0 ? 0 : ERROR_FAIL;
}
int build_hvm(struct libxl_ctx *ctx, uint32_t domid,
{
int ret;
+ if (info->kernel.mapped) {
+ XL_LOG_ERRNO(ctx, XL_LOG_ERROR, "build_hvm kernel cannot be mmapped");
+ return ERROR_INVAL;
+ }
+
ret = xc_hvm_build_target_mem(
ctx->xch,
domid,
(info->max_memkb - info->video_memkb) / 1024,
(info->target_memkb - info->video_memkb) / 1024,
- libxl_abs_path(ctx, (char *)info->kernel,
+ libxl_abs_path(ctx, (char *)info->kernel.path,
libxl_xenfirmwaredir_path()));
if (ret) {
XL_LOG_ERRNOVAL(ctx, XL_LOG_ERROR, ret, "hvm building failed");
if (c_info->hvm) {
b_info->shadow_memkb = 0; /* Set later */
b_info->video_memkb = 8 * 1024;
- b_info->kernel = "hvmloader";
+ b_info->kernel.path = "hvmloader";
b_info->hvm = 1;
b_info->u.hvm.pae = 1;
b_info->u.hvm.apic = 1;
printf("\t(image\n");
if (c_info->hvm) {
printf("\t\t(hvm\n");
- printf("\t\t\t(loader %s)\n", b_info->kernel);
+ printf("\t\t\t(loader %s)\n", b_info->kernel.path);
printf("\t\t\t(video_memkb %d)\n", b_info->video_memkb);
printf("\t\t\t(shadow_memkb %d)\n", b_info->shadow_memkb);
printf("\t\t\t(pae %d)\n", b_info->u.hvm.pae);
printf("\t\t)\n");
} else {
printf("\t\t(linux %d)\n", b_info->hvm);
- printf("\t\t\t(kernel %s)\n", b_info->kernel);
+ printf("\t\t\t(kernel %s)\n", b_info->kernel.path);
printf("\t\t\t(cmdline %s)\n", b_info->u.pv.cmdline);
- printf("\t\t\t(ramdisk %s)\n", b_info->u.pv.ramdisk);
+ printf("\t\t\t(ramdisk %s)\n", b_info->u.pv.ramdisk.path);
printf("\t\t)\n");
}
printf("\t)\n");
b_info->video_memkb = l * 1024;
if (!xlu_cfg_get_string (config, "kernel", &buf))
- b_info->kernel = strdup(buf);
+ b_info->kernel.path = strdup(buf);
if (c_info->hvm == 1) {
if (!xlu_cfg_get_long (config, "pae", &l))
b_info->u.pv.cmdline = cmdline;
if (!xlu_cfg_get_string (config, "ramdisk", &buf))
- b_info->u.pv.ramdisk = strdup(buf);
+ b_info->u.pv.ramdisk.path = strdup(buf);
}
if (!xlu_cfg_get_list (config, "disk", &vbds, 0)) {
c_val->target_memkb = Int64_val(Field(v, 3));
c_val->video_memkb = Int64_val(Field(v, 4));
c_val->shadow_memkb = Int64_val(Field(v, 5));
- c_val->kernel = String_val(Field(v, 6));
+ c_val->kernel.path = String_val(Field(v, 6));
c_val->hvm = Tag_val(Field(v, 7)) == 0;
infopriv = Field(Field(v, 7), 0);
if (c_val->hvm) {
} else {
c_val->u.pv.slack_memkb = Int64_val(Field(infopriv, 0));
c_val->u.pv.cmdline = String_val(Field(infopriv, 1));
- c_val->u.pv.ramdisk = String_val(Field(infopriv, 2));
+ c_val->u.pv.ramdisk.path = String_val(Field(infopriv, 2));
c_val->u.pv.features = String_val(Field(infopriv, 3));
}